package com.csg.ses.controller;

import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.baomidou.mybatisplus.extension.api.R;
import com.csg.ses.common.annotation.LoginToken;
import com.csg.ses.common.annotation.PassToken;
import com.csg.ses.common.configuration.SesConfig;
import com.csg.ses.common.utils.CommonUtil;
import com.csg.ses.common.utils.RedisUtil;
import com.csg.ses.entity.ses.SysEmployeeEntity;
import com.csg.ses.entity.ses.SysOrganizationEntity;
import com.csg.ses.entity.ses.SysUserLoginEntity;
import com.csg.ses.service.ses.*;
import com.csg.ses.vo.common.Result;
import com.csg.ses.vo.common.ResultStatus;
import com.csg.ses.vo.login.LoginInfo;
import com.csg.ses.vo.login.PwdVo;
import com.csg.ses.vo.login.UserView;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import sun.misc.BASE64Decoder;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.TimeUnit;

/**
 * 登录信息
 * @author cjj
 */
@RestController
@EnableConfigurationProperties(SesConfig.class)
@RequestMapping("")
@Api(tags = "登录接口")
public class SysUserLoginController {
    @Autowired
    private SysUserLoginService userLoginService;

    @Autowired
    private SysEmployeeService employeeService;

    @Autowired
    private SysOrganizationService organizationService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private SysRolesService rolesService;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private SesConfig sesConfig;

    /**
     * 本系统登录
     * @param userLogin
     * @return
     */
    @PostMapping("/login")
    @ApiOperation(value = "登录")
    @PassToken
    public Result<LoginInfo> login(@RequestBody SysUserLoginEntity userLogin) throws Exception {
        BASE64Decoder decoder = new BASE64Decoder();
        String textPwd = new String(decoder.decodeBuffer(userLogin.getLoginPwd())); //将base64加密的密码解成明文密码
        String md5Pwd = DigestUtils.md5DigestAsHex(textPwd.getBytes()); //md5加密
        if (userLogin != null && userLogin.getLoginCode() != null && !"".equals(userLogin.getLoginCode())) {
            SysUserLoginEntity user = userLoginService.getUserLogin(userLogin);
            if (user != null) {
                if (md5Pwd.equals(user.getLoginPwd())) {
                    LoginInfo loginInfo = null;
                    if (redisUtil.exists(user.getLoginId())) {    //从redis缓存获取登录信息
                        loginInfo = (LoginInfo) redisUtil.get(user.getLoginId());
                    } else {    //从数据库获取登录信息
                        userLogin.setLoginPwd(md5Pwd);
                        loginInfo = this.initLoginInfo(userLogin, user);
                        try {
                            redisUtil.set(user.getLoginId(), loginInfo, sesConfig.getTokenPeriod(), TimeUnit.MINUTES);    //登录信息放缓存里面，设置时效
                        } catch (Exception e) {
                            e.printStackTrace();
                            throw new RuntimeException();
                        }
                    }
                    return new Result(loginInfo, ResultStatus.SUCCESS);
                } else {
                    return new Result("登录失败，密码错误！", ResultStatus.LOGIN_FAIL);
                }
            } else {
                return new Result("登录失败,用户不存在！", ResultStatus.BIZ_FAILED);
            }
        } else {
            return new Result("登录账号不能为空！", ResultStatus.BIZ_FAILED);
        }
    }

    /**
     * 注销登录
     * @param request
     * @return
     */
    @PostMapping("/logout")
    @ApiOperation(value = "注销登录")
    @LoginToken
    public Result<String> logout(HttpServletRequest request) {
        try {
            String token = request.getHeader("token");   //从 http 请求头中取出 token
            String loginCode = JWT.decode(token).getAudience().get(0);
            SysUserLoginEntity user = userLoginService.getByLoginCode(loginCode);
            redisUtil.remove(user.getLoginId());    //将redis缓存中的loginInfo删除掉
            return new Result("注销成功！", ResultStatus.SUCCESS);
        } catch (Exception e) {
            e.printStackTrace();
            return new Result("注销失败！", ResultStatus.FAILED);
        }
    }

    @PostMapping("/modify-pwd")
    @ApiOperation(value = "修改密码")
    @LoginToken
    public Result modifyPwd(HttpServletRequest request, @RequestBody PwdVo pwdInfo) {
        try {
            if (pwdInfo != null && !CommonUtil.isEmpty(pwdInfo.getOldPwd()) && !CommonUtil.isEmpty(pwdInfo.getNewPwd())) {
                BASE64Decoder decoder = new BASE64Decoder();
                String oldPwd = new String(decoder.decodeBuffer(pwdInfo.getOldPwd())); //将base64加密的密码解成明文密码
                String md5OldPwd = DigestUtils.md5DigestAsHex(oldPwd.getBytes()); //md5加密
                String token = request.getHeader("token");   //从 http 请求头中取出 token
                String loginCode = JWT.decode(token).getAudience().get(0);
                SysUserLoginEntity user = userLoginService.getByLoginCode(loginCode);
                if (md5OldPwd.equals(user.getLoginPwd())) {
                    String newPwd = new String(decoder.decodeBuffer(pwdInfo.getNewPwd())); //将base64加密的密码解成明文密码
                    String md5NewPwd = DigestUtils.md5DigestAsHex(newPwd.getBytes()); //md5加密
                    userLoginService.modifyPwd(user, md5NewPwd);
                    redisUtil.removePattern(user.getLoginId());    //将redis缓存中的loginInfo删除掉
                    return new Result("密码修改成功！", ResultStatus.SUCCESS);
                } else {
                    return new Result("旧密码不正确！", ResultStatus.BIZ_FAILED);
                }
            } else {
                return new Result("旧密码和新密码不能为空！", ResultStatus.BIZ_FAILED);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new Result("修改密码失败！", ResultStatus.BIZ_FAILED);
        }
    }

    /**
     * 初始化登录信息
     * @param userLogin 登录信息（前端传入）
     * @param user 用户信息（数据库查询出来的）
     * @return
     */
    public LoginInfo initLoginInfo(SysUserLoginEntity userLogin, SysUserLoginEntity user) {
        LoginInfo loginInfo = new LoginInfo();
        loginInfo.setToken(tokenService.getToken(userLogin));   //token

        SysEmployeeEntity emp = employeeService.getUserLoginEmp(user.getEmpId());
        SysOrganizationEntity org = organizationService.getUserLoginOrg(emp.getOrgId());
        UserView userView = new UserView();
        userView.setLoginId(user.getLoginId());
        userView.setLoginCode(user.getLoginCode());
        userView.setEmpId(emp.getEmpId());
        userView.setEmpName(emp.getEmpName());
        userView.setOrgId(org.getOrgId());
        userView.setOrgCode(org.getOrgCode());
        userView.setOrgName(org.getOrgName());
        userView.setCollege(org.getCollege());
        userView.setEmpClass(org.getEmpClass());
        userView.setParentOrgId(org.getParentOrgId());
        userView.setLoginTime(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        userView.setRoles(rolesService.getUserRoles(user.getLoginId()));    //roles
        loginInfo.setUser(userView);    //user

        return loginInfo;
    }
}